#include <stdio.h>
#include "sys.h"
#include "Common_Types.h"
#include "stdlib.h"
#include "stdarg.h"

void message(int priority, const char * format, ...)
{
	va_list ap;
	va_start(ap, format);


	fprintf(stderr, "(CL %s) ",
		priority == LOG_EMERG ? "emergency" :
		priority == LOG_ALERT ? "alert" :
		priority == LOG_CRIT ? "critical" :
		priority == LOG_ERR ? "error" :
		priority == LOG_WARNING ? "warning" :
		priority == LOG_NOTICE ? "notice" :
		priority == LOG_INFO ? "info" :
		priority == LOG_DEBUG ? "debug" :
		"???");
	vfprintf(stderr, format, ap);

	va_end(ap);
}

TimeInternal subtractTime(const TimeInternal* t2, const TimeInternal* t1)
{
	TimeInternal tdif;
	tdif.nanoseconds = 0;
	tdif.seconds = 0;
	if(t2 == NULL || t1 == NULL)
	{
		PERROR("ERROR: subtractTime received NULL parameter\n");
		return tdif;
	}

	if(t2->nanoseconds < t1->nanoseconds)
	{
		tdif.nanoseconds = 1000000000 - t1->nanoseconds + t2->nanoseconds;
		tdif.seconds = t2->seconds - t1->seconds - 1;
	}
	else {
		tdif.seconds = t2->seconds - t1->seconds;
		tdif.nanoseconds = t2->nanoseconds - t1->nanoseconds;
	}
	return tdif;

}
TimeInternal addTime(const TimeInternal* t1, const TimeInternal* t2)
{
	TimeInternal sum;
	if(t2 == NULL || t1 == NULL)
	{
		PERROR("ERROR: subtractTime received NULL parameter\n");
		exit(0);
	}
	sum.nanoseconds = t1->nanoseconds + t2->nanoseconds;
	sum.seconds  = t1->seconds + t2->seconds;

	if(sum.nanoseconds >= 1000000000  )
	{
		sum.nanoseconds -= 1000000000;
		sum.seconds++;
	}
	return sum;

}
/*return 0 if t1 is greater than t2 *
 *return 1 if t2 is greater than t1 */
bool greaterThan(const TimeInternal* t1, const TimeInternal* t2)
{
	bool retVal;
	if(t2 == NULL || t1 == NULL)
	{
		PERROR("ERROR: subtractTime received NULL parameter\n");
		exit(0);
	}
	if(t1->seconds > t2->seconds ) {
		retVal = TRUE;
	}
	else if(t2->seconds > t1->seconds) {
		retVal = FALSE;
	}
	else {
		retVal = t1->nanoseconds > t2->nanoseconds;
	}
	return retVal;
}
bool nanoSleep(TimeInternal* t)
{
	struct timespec ts, tr;
	if(t == NULL)
	{
		PERROR("ERROR: subtractTime received NULL parameter\n");
		exit(0);
	}

	ts.tv_sec = t->seconds;
	ts.tv_nsec = t->nanoseconds;

	if (nanosleep(&ts, &tr) < 0) {
		t->seconds = tr.tv_sec;
		t->nanoseconds = tr.tv_nsec;
		return FALSE;
	}
	return TRUE;
}
void getTime(TimeInternal* time)
{

#if defined(linux)
	struct timespec tp;
	if (clock_gettime(CLOCK_REALTIME, &tp) < 0) {
		PERROR("clock_gettime() failed, exiting.");
		return;
	}
	time->seconds = tp.tv_sec;
	time->nanoseconds = tp.tv_nsec;
#elif defined(__CYGWIN__)
	struct timespec tp;
	if (clock_gettime(CLOCK_REALTIME, &tp) < 0) {
		PERROR("clock_gettime() failed, exiting.");
		return;
	}
	time->seconds = tp.tv_sec;
	time->nanoseconds = tp.tv_nsec;
#elif defined(__APPLE__)
	struct timeval tv;
	gettimeofday(&tv, 0);
	time->seconds = tv.tv_sec;
	time->nanoseconds = tv.tv_usec * 1000;
#else  /*WINDOWS*/
	/*
	struct timespec tp;
	if (clock_gettime(CLOCK_REALTIME, &tp) < 0) {
		PERROR("clock_gettime() failed, exiting.");
		exit(0);
	}
	time->seconds = tp.tv_sec;
	time->nanoseconds = tp.tv_nsec;*/

	time->seconds = 0;
	time->nanoseconds = 0;
#endif /* linux || __APPLE__ */
}

